package com.hefan.club.dynamic.service;

import com.alibaba.fastjson.JSON;
import com.cat.common.entity.Page;
import com.cat.common.entity.ResultBean;
import com.cat.common.meta.ResultCode;
import com.cat.tiger.service.JedisService;
import com.cat.tiger.util.GlobalConstants;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hefan.club.comment.meta.RedisKeyConstant;
import com.hefan.club.configCenter.ClubConfigCenter;
import com.hefan.club.dynamic.bean.Message;
import com.hefan.club.dynamic.dao.DynamicDao;
import com.hefan.club.dynamic.itf.DynamicService;
import com.hefan.club.dynamic.itf.SquareService;
import com.hefan.club.dynamic.itf.cache.RedisDynamicService;
import com.hefan.common.oss.OssImageService;
import com.hefan.notify.itf.ItemsStaticService;
import com.hefan.user.itf.WebUserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Map;

//import com.hefan.common.oss.OssImageService;
//import com.hefan.notify.itf.ItemsStaticService;

/**
 * Created by nigle on 2017/3/4.
 */
@Component("squareService")
public class SquareServiceImpl implements SquareService {

    @Resource
    private DynamicDao dynamicDao;

    @Resource
    private JedisService jedisService;
    @Resource
    WebUserService webUserService;
    @Resource
    OssImageService ossImageService;
    @Resource
    ItemsStaticService feeItemsStaticService;
    @Resource
    ClubConfigCenter clubConfigCenter;

    @Resource
    private DynamicService dynamicService;

    @Resource
    private RedisDynamicService redisDynamicService;

    private Logger logger = LoggerFactory.getLogger(SquareServiceImpl.class);


    /**
     * 获取广场下页信息
     */
    @Override
    public Page<Message> nextPageSquare(String minMessageId, String userId, Page po) {
        logger.info("nextPageSquare----开始----minMsgId:{},userId:{},po:{}",minMessageId,userId,JSON.toJSONString(po));
        StringBuilder ids = new StringBuilder();
        List<Message> listMessage = Lists.newArrayList();
        int start = 0;
        //messageId 为空则取首页，否则按索引值取下页
        if (StringUtils.isNotBlank(minMessageId)) {
            try {
                long messageIndex = jedisService.zrevrank(RedisKeyConstant.SQUARE_SORTED_KEY, minMessageId);
                if (messageIndex >= 0) {
                    start = (int)messageIndex + 1;
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("获取广场动态ID排序索引失败，messageID：{}", minMessageId);
                return null;
            }
        }

        //广场动态最多展示4000条,设置是否到底
        if (start >= (1000 - po.getPageSize())) {
            po.setTotalItems(po.getPageSize());
        }else {
            po.setTotalItems(po.getPageSize()*2);
        }
        //拼装数据
        try {
            List listId = jedisService.zrevrange(RedisKeyConstant.SQUARE_SORTED_KEY, start, start + po.getPageSize() - 1);
            if (listId.size() > 0) {
                logger.info("首页或下页数据list{}",listId.toString());
                //拼装数据
                listMessage = fixData(listId, userId);
                po.setResult(listMessage);
            }else {
                logger.error("获取广场页排序列表List失败，list.size={}",listId.size());
                initSquareList(100);
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("广场首页缓存信息获取失败");
            return null;
        }
        return po;
    }

    /**
     * 刷新广场页数据
     */
    @Override
    public Page<Message> flushSquare(String maxMessageId, String userId, Page po) {
        logger.info("刷新广场页数据 params maxMessageId={},userId={},pageNo={},pageSize={}", maxMessageId, userId, po.getPageNo(), po.getPageSize());
        //拼装数据
        try {
            List listId = jedisService.zrevrange(RedisKeyConstant.SQUARE_SORTED_KEY, 0, po.getPageSize() - 1);
            if (listId.size() > 0) {
                logger.info("刷新数据list{}",listId.toString());
                List<Message> listMessage = fixData(listId, userId);
                po.setResult(listMessage);
            }else {
                logger.error("获取广场页排序列表List失败，list.size<=0");
                initSquareList(100);
                return po;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("广场首页刷新信息获取失败");
            return po;
        }
        return po;
    }

    /**
     * 缓存动态信息和排序ID
     */
    @Override
    public void setMessageToRdis(String messageId) {
        if (StringUtils.isBlank(messageId)) {
            logger.info("缓存动态信息和排序ID 传入参数为空");
            return;
        }
        //setDataToRedis(messageId);
        setSortedToRedis(messageId);
    }

    /**
     * 删除动态信息和排序ID
     */
    @Override
    @Deprecated
    public void delMessageToRdis(String messageId) {
        if (StringUtils.isBlank(messageId)) {
            logger.info("删除动态信息和排序ID 传入参数为空");
            return;
        }
        //delDataToRedis(messageId);
        delSortedToRedis(messageId);
    }


    /**
     * 缓存排序动态ID
     */
    @Override
    public void setSortedToRedis(String messageId){
        try {
            Message message=dynamicDao.getMessageById(messageId);
            if(message ==null){
                return ;
            }
            //缓存动态
            redisDynamicService.syncMessage(message);
            Long l = jedisService.zadd(RedisKeyConstant.SQUARE_SORTED_KEY, Double.valueOf(messageId), messageId);
            logger.info("messageId:{},缓存排序返回影响行数{}", messageId, l);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("messageId:{},缓存排序失败！",messageId);
        }
    }

    /**
     * 删除排序动态ID
     */
    private void delSortedToRedis(String messageId){
        try {
            Long l = jedisService.zrem(RedisKeyConstant.SQUARE_SORTED_KEY, messageId);
            logger.info("messageId:{},删除排序返回影响行数{}", messageId, l);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("messageId:{},删除缓存排序失败！",messageId);
        }
    }

    /**
     * 拼装动态数据
     * @param listId
     * @param userId
     * @return
     */
    private List<Message> fixData(List listId,String userId) {
        List<Message> listMessage = Lists.newArrayList();
        for (Object o : listId) {
            if (null == o){
                continue;
            }
            Message message = dynamicService.getCacheMessageInfo(String.valueOf(o), userId);
            if (null != message) {
                //列表页评论数=礼物数+评论数
                message.setCommentCount(message.getPresentCount() + message.getCommentCount());
                listMessage.add(message);
            }
           /* logger.info("拼装动态数据 messgeId={}", o);
            if (null == o){
                continue;
            }
            Message message;
            String mesStr = getDataFromRedis(String.valueOf(o));
            if (StringUtils.isBlank(mesStr)) {
                logger.info("messageId:{}缓存中无数据，查询MySql,并加入缓存",o);
                message = getDataByMsgId(String.valueOf(o));
                if (null != message) {
                    setDataToRedis(message);
                }
            }else {
                message = JSON.parseObject(mesStr, Message.class);
            }
            if (null != message) {
                //评论数 礼物数合并
//                message.setCommentCount(message.getPresentCount()+message.getCommentCount());
                //格式化时间（几分钟前）
                message.setMessageTimes(DynamicDateCal.getDaysBeforeNow(message.getMessageTime()));
                //拼接点赞状态
                message.setPraiseType(0);
                Double d = -1.0;
                try {
                    key = String.format(RedisKeyConstant.PRAISE_SORTED_KEY, String.valueOf(message.getMessageId()));
                    d = jedisService.zscore(key, userId);
                    logger.info("动态：{}的点赞列表，key：{}，userId：{}的score：{}",message.getMessageId(),key,userId,d);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("获取userId:{}对messageId:{}的点赞状态失败",userId,message.getMessageId());
                }
                if (null != d && d > 0) {
                    message.setPraiseType(1);
                }
                listMessage.add(message);
            }*/
        }
        return listMessage;
    }

    /**
     * 初始化广场1000条动态
     */
    @Override
    public ResultBean initSquareList(int count) {
        List<Message> listMessage = dynamicDao.getSquareMessage(count);
        if (listMessage.size() > 0) {
            try {
                jedisService.del(RedisKeyConstant.SQUARE_SORTED_KEY);
            } catch (Exception e) {
                e.printStackTrace();
            }
            for (Message message : listMessage) {
                if (message!=null) {
                    // 同步到广场排序
                    setSortedToRedis(String.valueOf(message.getMessageId()));
                    //setMessageToRdis(message);
                    //初始化点赞列表,有则不存
//                    initPraiseForMessage(String.valueOf(message.getMessageId()));
                }
            }
        }

        try {
            //刷新小红点是否刷新的标记
            jedisService.incr(RedisKeyConstant.SQUARE_LATEST_KEY);
            Long l = jedisService.zcard(RedisKeyConstant.SQUARE_SORTED_KEY);
            if (null != l) {
                logger.info("初始化完成，广场排序缓存长度：{}", l);
                return new ResultBean(ResultCode.SUCCESS, l);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取广场排序列表缓存长度失败");
        }
        return new ResultBean(ResultCode.SUCCESS);
    }

    /**
     * 刷新广场小红点
     */
    @Override
    public void squareLatest(){
        String latestId = "";
        Map<String, String> config = clubConfigCenter.getPublicConfig();
        String path = config.get("square.red.path") ;
        logger.info("路径获取：{}", path);
        try {
            String isFlush = jedisService.getStr(RedisKeyConstant.SQUARE_LATEST_KEY);
            if (StringUtils.isBlank(isFlush)) {
                logger.info("刷新广场最新动态：没有新动态生成");
                return;
            }
            List list = jedisService.zrevrange(RedisKeyConstant.SQUARE_SORTED_KEY,0,0);
            if (list.size() == 0){
                logger.error("刷新广场最新动态获取失败");
                return;
            }else {
                latestId = list.get(0).toString();
                ResultBean rb = new ResultBean(ResultCode.SUCCESS);
                Map map = Maps.newHashMap();
                map.put("msgId", latestId);
                rb.setData(map);
                ByteArrayInputStream buf = new ByteArrayInputStream(JSON.toJSONString(rb).getBytes("utf-8"));
                ossImageService.updataFile(GlobalConstants.PIC_OSS_BUCKET, buf, buf.available(), path + "squareLatest.js");
                logger.info("刷新广场最新动态ID：{}", latestId);
            }
            //删除标记
            jedisService.del(RedisKeyConstant.SQUARE_LATEST_KEY);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取广场最新动态ID缓存失败");
        }

    }


    /**
     * 动态新增时更新缓存
     * @param addMessageIdList 新增操作
     */
    @Override
    @Async
    public void addSquareRedisForMessage(List<Map<String,Object>> addMessageIdList) {
        if (addMessageIdList.size() > 0) {
            logger.info("新增动态，更新缓存，开始");
            String mesId;
            for (Map<String,Object> map : addMessageIdList) {
                mesId = String.valueOf(map.get("messageId"));
                logger.info("更新缓存：新增动态ID{}", mesId);
                setMessageToRdis(mesId);
            }
            logger.info("新增动态，更新缓存，结束");
            checkReidsLength();
        }else {
            logger.info("入参为空");
        }
    }
    /**
     * 动态删除时更新缓存
     * @param delMessageIdList 删除操作
     */
    @Override
    @Async
    public void delSquareRedisForMessage(List<Map<String,Object>> delMessageIdList) {
        if (delMessageIdList.size() > 0) {
            logger.info("删除动态，更新缓存，开始");
            String messageId;
            for (Map<String,Object> map : delMessageIdList) {
                messageId = String.valueOf(map.get("messageId"));
                logger.info("更新缓存：删除动态ID{}",messageId);
                delSortedToRedis(messageId);
            }
            logger.info("删除动态，更新缓存，结束");
            checkReidsLength();
        }else {
            logger.info("入参为空");
        }
    }

    /**
     * 检查广场列表缓存
     * 多退少补
     */
    @Async
    private void checkReidsLength() {
        try {
            Long l = jedisService.zcard(RedisKeyConstant.SQUARE_SORTED_KEY);
            if (null != l) {
                logger.info("广场列表排序缓存长度：{}", l);
                if (l > 1200) {
                    Long result = jedisService.zremrangeByRank(RedisKeyConstant.SQUARE_SORTED_KEY, 0, l - 1000);
                    if (null != result) {
                        logger.info("广场列表排序缓存清除数据{}行", result);
                    }else {
                        logger.error("广场排序列表缓存清除数据失败");
                    }
                }
                if (l < 800) {
                    //刷新缓存
                    initSquareList(1000);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取排序长度失败");
        }
    }

    /**
     * 初始化点赞数据
     * @param messageId
    */
    @Override
    public void initPraiseForMessage(String messageId) {
        logger.info("初始化点赞数据，开始");
        try {
            Long l = jedisService.del(String.format(RedisKeyConstant.PRAISE_SORTED_KEY, messageId));
            logger.info("删除已赞缓存返回行数{}",l);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("删除已赞缓存失败");
        }
        String userId;
        List<Map<String, Object>> listId = dynamicDao.getMessageOfPraise(messageId);
        if(null != listId && listId.size()>0){
            for (Map<String, Object> map : listId) {
                userId = String.valueOf(map.get("userId"));
                Long l = setPraiseToRedis(userId, messageId);
                logger.info("userId：{} 点赞动态{},返回行数{}", userId, messageId, l);
            }
        }

        logger.info("初始化点赞数据，结束");
    }

    /**
     * 缓存用户点赞动态信息
     */
    @Override
    public Long setPraiseToRedis(String userId, String messageId) {
        try {
            long score = System.currentTimeMillis();
            Long l = jedisService.zadd(String.format(RedisKeyConstant.PRAISE_SORTED_KEY, messageId), (double)score, userId);
            logger.info("缓存userId:{}点赞MessageId:{}返回影响行数{}", userId, messageId, l);
            return l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("缓存用户点赞失败,userId:{},messageId:{}", userId, messageId);
            return null;
        }
    }

/*
    *//**
     * 获取缓存中动态信息
     *//*
    private String getDataFromRedis(String messageId){
        try {
            return jedisService.hgetStr(RedisKeyConstant.SQUARE_HASHSET_KEY, messageId);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取缓存中动态信息失败");
            return null;
        }
    }*/

   /* *//**
     * 缓存动态信息
     *//*
    private void setDataToRedis(Message mes){
        try {
            if (null != mes) {
                Long l = jedisService.hset(RedisKeyConstant.SQUARE_HASHSET_KEY, String.valueOf(mes.getMessageId()), JSON.toJSONString(mes));
                logger.info("messageId:{},缓存正文信息返回影响行数{}", mes.getMessageId(), l);
            }else {
                logger.error("正文信息为空！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取动态信息数据失败");
        }
    }*/

    /**
     * 删除动态信息

     private void delDataToRedis(String messageId){
     try {
     Long l = jedisService.hdel(RedisKeyConstant.SQUARE_HASHSET_KEY, messageId);
     logger.info("messageId:{},删除正文信息返回影响行数{}", messageId, l);
     } catch (Exception e) {
     e.printStackTrace();
     logger.error("删除动态信息数据失败");
     }
     } */

    /**
     * 动态变更时更新缓存
     * @param editMessageIdList 信息变化
     *//*
    @Override
    @Async
    @Deprecated
    public void updateSquareRedisForMessage(List<Map<String,Object>> editMessageIdList) {
        if (editMessageIdList.size() > 0) {
            logger.info("更改动态，更新缓存，开始");
            String mesId;
            for (Map<String,Object> map : editMessageIdList) {
                mesId = String.valueOf(map.get("messageId"));
                logger.info("更新缓存：更新动态ID{}",mesId);
                setMessageToRdis(mesId);

            }
            logger.info("更改动态，更新缓存，结束");
        }else {
            logger.info("入参为空");
        }
    }*/
    /**
     * 获取单条数据
     */
    /*
    @Override
    public Message getDataByMsgId(String messageId) {

        logger.info("查询动态数据messageId={}", messageId);
        if (StringUtils.isBlank(messageId)) {
            logger.error("查询动态数据为空messageId={}", messageId);
            return null;
        }
        logger.info("查询的MessageID：{}",messageId);
        List<DynamicAlbum> listPhoto = dynamicAlbumDao.photoListForMessage(messageId);
        Message mes = dynamicDao.getMessageById(messageId);
        List other = new ArrayList();
        if (Integer.valueOf(mes.getMessageType()) == MessageConstant.VIDEOS) {
            Map pho = new HashMap();
            pho.put("pictureUrls", mes.getPath());
            pho.put("year", "");
            pho.put("month", "");
            other.add(pho);
        }
        if (Integer.valueOf(mes.getMessageType()) == MessageConstant.PICTURE) {
            for (int i = 0; i < listPhoto.size(); i++) {
                Map pho = new HashMap();
                pho.put("pictureUrls", listPhoto.get(i).getPath());
                pho.put("year", "");
                pho.put("month", "");
                other.add(pho);
            }
        }
        if (Integer.valueOf(mes.getMessageType()) == MessageConstant.WORDS) {
            Map pho = new HashMap();
            pho.put("pictureUrls", "");
            pho.put("year", "");
            pho.put("month", "");
            other.add(pho);
        }
        WebUser user = webUserService.findUserInfoFromCache(mes.getUserId());
        if (null == user) {
            logger.error("用户{}不存在！！！！", mes.getUserId());
            return null;
        }
        if (user.getState() != 0 || user.getIsDel() == 1 || user.getSuperiorState() != 0) {
            return null;
        }
        mes.setNickName(user.getNickName());
        mes.setHeadImg(user.getHeadImg());
        mes.setUserType(String.valueOf(user.getUserType()));
        mes.setArticleContent(other);
        logger.info("message拼装数据：{}", mes);
        return mes;
    }
*/



    /**
     * 缓存动态信息

     @Override
     public void setDataToRedis(String messageId){
     try {
     Message mes = getDataByMsgId(messageId);
     if (null != mes) {
     redisDynamicService.syncMessage(mes);
     logger.info("message:{},缓存正文信息返回影响行数", JSON.toJSONString(mes));
     }else {
     logger.error("messageId:{},获取正文信息失败！", messageId);
     }
     } catch (Exception e) {
     e.printStackTrace();
     logger.error("获取动态信息数据失败", e);
     }
     }*/

    /**
     * 初始化动态的点赞数据(用于检查动态点赞状态)
     * @return
     */
    @Override
    @Async
    public ResultBean initPraiseForMessageCache() {
        List<Message> listMessage = dynamicDao.getAllMessage();
        int count = 1;
        if (listMessage.size() > 0) {
            for (Message message : listMessage) {
                if (message!=null) {
                    initPraiseForMessage(String.valueOf(message.getMessageId()));
                }
                logger.info("动态{}的点赞完成,第{}个",message.getMessageId(),count);
                count ++;
            }
        }
        return new ResultBean(ResultCode.SUCCESS,count);
    }

}
